package com.yaha.controler.touchpad;

import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.yaha.controler.devices.pojo.MdnsDevice;
import com.yaha.controler.remote.bean.KeyInfo;
import com.yaha.controler.utils.MyLog;

public class TouchpadTouchEventHandlerListener implements OnTouchListener {
	private final static String TAG = TouchpadTouchEventHandlerListener.class.getSimpleName();

	private View mView;
	private int viewHight;
	private int viewWidth;

	private static final long INTERVAL_TIME = 1000;
	private Point downPoint = new Point();
	private Point movePoint = new Point();
	private Point lastPoint = new Point();
	private Point inflexPoint = new Point();

	private MdnsDevice mDevice;
	private Context mContext;

	/** 消息指令发送是否许可 */
	private boolean command_available;
	/** 命令是否超时的判断变量 */
	private boolean command_timeout = false;
	/** 是否是长按标识变量 */
	private boolean isLongPress = false;
	/** 命令键值 */
	private int keyAction = -1;
	// X轴，Y轴偏移量
	private float x_distance = 0;
	private float y_distance = 0;
	private long last_move_time = 0;
	private int inflexion_num = 0;

	private int x_state = -1;
	private int y_state = -1;

	private int slide_cmd = -1;

	// 标识滑动最小距离的分割值
	private static final int MIN_SLIDE_GAP = 15;
	private static final int MIN_SLIDE_DISTANCE = 20;
	private static final int MIN_CLICK_GAP = 10;
	private static final int MIN_SLIDE_BACK_GAP = 30;

	private static final int SLIDE_POINT_UP = 0;
	private static final int SLIDE_POINT_DOWN = 1;
	private static final int SLIDE_POINT_PAUSE = 2;

	// 对应遥控器功能键的键值
	private static final int CMD_SLIDE_UP = 0;
	private static final int CMD_SLIDE_DOWN = 1;
	private static final int CMD_SLIDE_LEFT = 2;
	private static final int CMD_SLIDE_RIGHT = 3;
	private static final int CMD_SLIDE_BACK = 4;
	private static final int CMD_SLIDE_CLICK = 5;

	public TouchpadTouchEventHandlerListener(View mView, MdnsDevice mDevice, Context mContext) {
		this.mView = mView;
		this.mDevice = mDevice;
		this.mContext = mContext;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		if (null != mView && (viewHight == 0 || viewWidth == 0)) {
			viewHight = mView.getHeight();
			viewWidth = mView.getWidth();
		}
		handleTouch(event);
		return true;
	}

	private void handleTouch(MotionEvent event) {
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			MyLog.i(TAG, "ACTION_DOWN");
			float d_x = event.getX();
			float d_y = event.getY();
			lastPoint.setPoint(d_x, d_y, 0);
			downPoint.setPoint(d_x, d_y, 0);
			command_available = true;
			last_move_time = event.getDownTime();
			MyLog.i(TAG, "ACTION_DOWN" + "--x-->" + downPoint.getX_point() + "--y-->" + downPoint.getY_point());
			if (null != mView) {
				mView.setX(d_x - viewWidth / 2);
				mView.setY(d_y - viewHight / 2);
				mView.setVisibility(View.VISIBLE);
			}

			break;
		case MotionEvent.ACTION_MOVE:

			float m_x = event.getX();
			float m_y = event.getY();

			movePoint.setPoint(m_x, m_y, 0);

			if (null != mView) {
				mView.setX(movePoint.getX_point() - viewWidth / 2);
				mView.setY(movePoint.getY_point() - viewHight / 2);
			}

			if (command_available) {

				x_distance = movePoint.getX_point() - downPoint.getX_point();

				y_distance = movePoint.getY_point() - downPoint.getY_point();

				float x_gap = movePoint.getX_point() - lastPoint.getX_point();
				if (Math.abs(x_gap) > MIN_SLIDE_GAP) {
					lastPoint.setX_point(movePoint.getX_point());
					x_state = operateDistance(x_gap, x_state);
				}

				float y_gap = movePoint.getY_point() - lastPoint.getY_point();
				if (Math.abs(y_gap) > MIN_SLIDE_GAP) {
					lastPoint.setY_point(movePoint.getY_point());
					y_state = operateDistance(y_gap, y_state);
				}

				if (inflexion_num == 1 && inflexPoint.getX_point() == 0 && inflexPoint.getY_point() == 0) {
					inflexPoint.setPoint(m_x, m_y, 0);
				}

				if (!isLongPress) {
					initCommand();
					if (MyLog.DBUG) {
						float time = event.getEventTime() - event.getDownTime();
						float SEND_GAP = event.getEventTime() - last_move_time;
						MyLog.d(TAG, "time=" + time);
						MyLog.d(TAG, "SEND_GAP=" + SEND_GAP);
						MyLog.d(TAG, "isLongPress=" + isLongPress);
					}
					if (event.getEventTime() - event.getDownTime() > INTERVAL_TIME) {
						command_timeout = true;
						MyLog.d(TAG, "values change : keyAction=" + keyAction);
						keyAction = 1;
						MyLog.d(TAG, "Now values change : keyAction=" + keyAction);
						isLongPress = true;
						reponseCommand();
					}
				}

				if (inflexion_num > 1) {
					command_available = false;
				}
			}
			MyLog.i(TAG, "ACTION_MOVE" + "--x-->" + movePoint.getX_point() + "--y-->" + movePoint.getY_point());
			break;

		case MotionEvent.ACTION_UP:
			MyLog.i(TAG, "ACTION_UP->Begin");
			// 由于点击事件可以不走move，所以在up时多为点击做一次判断
			if (command_available && inflexion_num == 0
					&& Math.abs(event.getX() - downPoint.getX_point()) < MIN_CLICK_GAP
					&& Math.abs(event.getY() - downPoint.getY_point()) < MIN_CLICK_GAP) {
				slide_cmd = CMD_SLIDE_CLICK;
			}
			if (null != mView) {
				mView.setX(event.getX() - viewWidth / 2);
				mView.setY(event.getY() - viewHight / 2);
				mView.setVisibility(View.INVISIBLE);
			}

			if (isLongPress) {
				keyAction = 0;
			}
			if (command_available || isLongPress) {
				reponseCommand();
			}
			resetData();
			break;
		}
	}

	/**
	 * <功能描述>判断触摸点移动方式
	 * 
	 * @param lastState
	 * @param currentState
	 * @return
	 */
	private int operateDistance(float lastState, int currentState) {
		MyLog.i(TAG, "operateDistance-->Begin-->" + lastState + "-->" + currentState);
		if (lastState > 0) {
			if (currentState == SLIDE_POINT_DOWN) {
				inflexion_num++;
			}
			return SLIDE_POINT_UP;
		} else if (lastState < 0) {
			if (currentState == SLIDE_POINT_UP) {
				inflexion_num++;
			}
			return SLIDE_POINT_DOWN;
		}
		return SLIDE_POINT_PAUSE;
	}

	/**
	 * <功能描述>将所有标识变量置为初始状态
	 */
	private void resetData() {
		command_available = false;
		command_timeout = false;
		x_distance = y_distance = 0;
		x_state = y_state = -1;
		inflexion_num = 0;
		slide_cmd = -1;
		keyAction = -1;
		isLongPress = false;
		downPoint.resetPoint();
		movePoint.resetPoint();
		lastPoint.resetPoint();
		inflexPoint.resetPoint();
	}

	/**
	 * <功能描述>初始化键值指令集
	 */
	private void initCommand() {
		// 如果拐点数目为零，则执行的简单的上下左右操作，有拐点的话执行是返回操作
		if (inflexion_num == 0) {
			if (Math.abs(x_distance) < MIN_CLICK_GAP && Math.abs(y_distance) < MIN_CLICK_GAP) {
				slide_cmd = CMD_SLIDE_CLICK;
			} else if (Math.abs(x_distance) - Math.abs(y_distance) > MIN_SLIDE_GAP) {
				if (movePoint.getX_point() - downPoint.getX_point() > MIN_SLIDE_DISTANCE) {
					slide_cmd = CMD_SLIDE_RIGHT;
				} else if (downPoint.getX_point() - movePoint.getX_point() > MIN_SLIDE_DISTANCE) {
					slide_cmd = CMD_SLIDE_LEFT;
				}
			} else if (Math.abs(y_distance) - Math.abs(x_distance) > MIN_SLIDE_GAP) {
				if (movePoint.getY_point() - downPoint.getY_point() > MIN_SLIDE_DISTANCE) {
					slide_cmd = CMD_SLIDE_DOWN;
				} else if (downPoint.getY_point() - movePoint.getY_point() > MIN_SLIDE_DISTANCE) {
					slide_cmd = CMD_SLIDE_UP;
				}
			}
		} else if (inflexion_num == 1 && y_distance > MIN_SLIDE_BACK_GAP
				&& Math.abs(inflexPoint.getX_point() - downPoint.getX_point()) > MIN_SLIDE_BACK_GAP
				&& Math.abs(inflexPoint.getX_point() - movePoint.getX_point()) > MIN_SLIDE_BACK_GAP) {
			slide_cmd = CMD_SLIDE_BACK;
		} else {
			slide_cmd = -1;
		}
	}

	/**
	 * <功能描述>根据对应的键值，开始发送对应的指令
	 */
	private void reponseCommand() {
		switch (slide_cmd) {
		case CMD_SLIDE_UP:
			sendKeyValueMsg(KeyInfo.KEYCODE_DPAD_UP, keyAction);
			MyLog.d(TAG, "action->UP,keyAction=" + keyAction);
			break;
		case CMD_SLIDE_DOWN:
			sendKeyValueMsg(KeyInfo.KEYCODE_DPAD_DOWN, keyAction);
			MyLog.d(TAG, "action->DOWN,keyAction=" + keyAction);
			break;
		case CMD_SLIDE_LEFT:
			sendKeyValueMsg(KeyInfo.KEYCODE_DPAD_LEFT, keyAction);
			MyLog.d(TAG, "action->LEFT,keyAction=" + keyAction);
			break;
		case CMD_SLIDE_RIGHT:
			sendKeyValueMsg(KeyInfo.KEYCODE_DPAD_RIGHT, keyAction);
			MyLog.d(TAG, "action->RIGHT,keyAction=" + keyAction);
			break;
		case CMD_SLIDE_BACK:
			if (!command_timeout) {
				sendKeyValueMsg(KeyInfo.KEYCODE_BACK, keyAction);
				MyLog.d(TAG, "action->BACK,keyAction=" + keyAction);
			}
			break;
		case CMD_SLIDE_CLICK:
			if (!command_timeout) {
				sendKeyValueMsg(KeyInfo.KEYCODE_DPAD_CENTER, keyAction);
				MyLog.d(TAG, "action->CLICK,keyAction=" + keyAction);
			}
			break;
		}
	}

	/**
	 * <功能描述>发送对应的键值
	 * 
	 * @param keyCode
	 * @param action
	 */
	public void sendKeyValueMsg(int keyCode, int action) {
		if (mDevice != null && null != mDevice.adapter()) {
			if (action == -1) {
				// 如果action==-1，说明是固定的上下左右的键值，不需要发送Action
				mDevice.adapter().key(mDevice, keyCode);
			} else {
				mDevice.adapter().key(mDevice, keyCode, action);
			}
		}
	}
}
